<?php
// +----------------------------------------------------------------------
// | 登录服务服务层
// +----------------------------------------------------------------------
// | 主要服务于登录数据处理
// +----------------------------------------------------------------------
// | 错误编码头 209xxx
// +----------------------------------------------------------------------
namespace common\service;

use common\exception\LogicException;
use common\model\StatusModel;
use common\model\TaskClockModel;
use common\model\TaskModel;
use common\model\TaskWorkOrderModel;
use common\model\UncloseTaskClockModel;
use common\model\UserModel;
use common\model\VersionModel;
use support\ErrorCode;
use think\Exception;
use think\module\Module;

class TaskClockService
{
    private $taskClockModel;

    /**
     * VersionService constructor.
     */
    public function __construct()
    {
        $this->taskClockModel = model(TaskClockModel::class);
    }

    /**
     * 创建任务提醒时钟
     * @param $data
     * @param $currentUserId
     * @return array|bool|int|string
     * @throws \Exception
     */
    public function createTaskClock($data, $currentUserId)
    {
        $taskIds = $data['task_id'];
        $clockTime = $data['time'];

        // 限制最多给批量给50个任务增加提醒闹钟
        if (count($taskIds) >= 50) {
            throw_strack_exception('task sum exceed the limit', ErrorCode::TASK_SUM_EXCEED_THE_LIMIT);
        }

        $task = model(TaskModel::class)->where(["id" => ["IN", $taskIds]])->field('id,plan_end_time,plan_start_time')->select();
        if (empty($task)) {
            throw_strack_exception('task no exist', ErrorCode::TASK_NOT_EXIST);
        }

        //  $minTaskPlanEndTime = min(array_column($task, 'plan_end_time'));
        //  $maxTaskPlanEndTime = max(array_column($task, 'plan_start_time'));
        // 任务最小计划截止时间
        $minTaskPlanEndTime = 9999999999;
        // 任务最大计划开始时间
        $maxTaskPlanEndTime = 0;
        foreach ($task as $taskItem) {
            if ($taskItem['plan_end_time'] < $minTaskPlanEndTime) {
                $minTaskPlanEndTime = $taskItem['plan_end_time'];
            }

            if ($taskItem['plan_start_time'] > $maxTaskPlanEndTime) {
                $maxTaskPlanEndTime = $taskItem['plan_start_time'];
            }
        }

        //时间不能超过结束计划结束以及计划开始时间
        if ($data['time'] > $minTaskPlanEndTime && $data['time'] < $maxTaskPlanEndTime) {
            throw_strack_exception('task clock time cannot exceed the limit', ErrorCode::TASK_CLOCK_TIME_CANNOT_EXCEED_THE_LIMIT);
        }

        $taskClockCount = model(TaskClockModel::class)->where(['task_id' => ['IN', $taskIds]])
            ->field('count(task_id) as task_clock_count')
            ->group('task_id')
            ->select();

        $taskClockCount = array_column($taskClockCount, 'task_clock_count');
        $clockTimeCount = count($clockTime);
        $maxTaskClockCount = !empty($taskClockCount) ? max($taskClockCount) : 0;

        //限制只能创建十个
        if (($clockTimeCount + $maxTaskClockCount) > 10) {
            throw_strack_exception('task clock sum cannot exceed the limit', ErrorCode::TASK_CLOCK_CANNOT_EXCEED_THE_LIMIT);
        }

        $addTaskClockData = [];
        $clockTime = array_unique($clockTime);
        foreach ($taskIds as $taskId) {
            foreach ($clockTime as $clockTimeItem) {
                $addTaskClockData[] = [
                    'task_id' => $taskId,
                    'time' => $clockTimeItem
                ];
            }
        }
        //查询出相关任务的闹钟
        $taskClockList = model(TaskClockModel::class)->where(['task_id' => ['IN', $taskIds]])->field('id,task_id,time')->select();
        $taskClockArray = [];
        foreach ($taskClockList as $taskClockListItem) {
            $key = md5("{$taskClockListItem['task_id']}_{$taskClockListItem['time']}");
            $taskClockArray[$key] = $taskClockListItem;
        }
        $addTaskClockDataArray = [];
        foreach ($addTaskClockData as $addTaskClockDataItem) {
            $key = md5("{$addTaskClockDataItem['task_id']}_{$addTaskClockDataItem['time']}");
            $addTaskClockDataArray[$key] = $addTaskClockDataItem;
        }
        //比较出新的插入数据
        $addData = array_diff_key($addTaskClockDataArray, $taskClockArray);
        $taskClockModel = model(TaskClockModel::class);

        $taskClock = [];
        if (!empty($addData)) {
            $addData = array_values($addData);
            $addData = array_map(function ($addDataItem) use ($currentUserId) {
                $addDataItem['created_by'] = $currentUserId;
                $addDataItem['created'] = time();
                return $addDataItem;
            }, $addData);
            $taskClock = $taskClockModel->addAll($addData);
            if ($taskClock) {
                $addDataTaskIds = array_column($addData, 'task_id');
                //比较出最新的
                $diffTaskClockList = model(TaskClockModel::class)->where(['task_id' => ['IN', $taskIds]])->field('id,task_id')->select();
                $diffTaskClockListIds = array_column($diffTaskClockList, null, 'id');
                $taskClockListIds = array_column($taskClockList, null, 'id');
                //新增的闹钟
                $newTaskClock = array_diff_key($diffTaskClockListIds, $taskClockListIds);
                try {
                    $taskClockModel->startTrans();
                    model(TaskModel::class)->where(["id" => ['IN', $addDataTaskIds]])->save(["clock_status" => "to_set"]);
                    //查询公司所有的 （生产制片） 需要给每个人以及当前用户推一条未关闭的闹钟
                    if (!empty($newTaskClock)) {
                        $this->pushUncloseTaskClock($newTaskClock, [$currentUserId]);
                    }

                    $taskClockModel->commit();
                } catch (\Throwable $exception) {
                    $taskClockModel->rollback();
                    throw_strack_exception($exception->getMessage(), $exception->getCode());
                }
            }
        }
        return $taskClock;
    }

    /**
     * 需要给每个人推一条未关闭的闹钟
     * @param $taskClock
     * @param $otherUser
     * @return array
     * @throws \Exception
     */
    public function pushUncloseTaskClock($taskClock, $otherUser = [])
    {
        $producerUser = teamones_request('teamones-im', 'tenant/select_tenant_user', [
            "param" => [
                "filter" => [
                    "role.code" => ["-in", 'step_producer,executive_producer']
                ],
                "fields" => "user.id"
            ]
        ])['data'];
        $producerUser = $producerUser ?? [];
        if (empty($producerUser)) {
            throw new LogicException("not exist required producer ", ErrorCode::NOT_EXIST_REQUIRED_PRODUCER);
        }

        //给所有的环节制片设置未关闭闹钟
        $producerUserIds = array_column($producerUser, 'user_id');
        $userIds = model(UserModel::class)->where([
            'union_id' => ['IN', $producerUserIds]
        ])->field('id')->column('id');
        $userIds = array_unique(array_merge($otherUser, $userIds));
        $saveData = [];
        foreach ($taskClock as $taskClockItem) {
            foreach ($userIds as $userId) {
                $saveData[] = [
                    'user_id' => $userId,
                    'task_id' => $taskClockItem['task_id'],
                    'task_clock_id' => $taskClockItem['id']
                ];
            }
        }

        model(UncloseTaskClockModel::class)->addAll($saveData);

        return $producerUser;
    }

    /**
     * 关闭任务时钟
     * @param $filter
     * @return false|int|mixed|string
     */
    public function closeTaskClock($filter)
    {
        //闹钟关闭
        $uncloseTaskClockList = model(UncloseTaskClockModel::class)->where($filter)->field('id')->select();

        $count = 0;
        if (!empty($uncloseTaskClockList)) {
            $taskClockIds = array_column($uncloseTaskClockList, 'id');
            $count = model(UncloseTaskClockModel::class)->where(['id' => ["IN", $taskClockIds]])->delete();
        }

        return $count;
    }

    /**
     * 删除任务闹钟
     * @param $filter
     * @return false|int|mixed|string
     */
    public function deleteTaskClock($filter)
    {
        $taskClock = 0;
        $taskClockList = model(TaskClockModel::class)->where($filter)->field('id')->select();
        if (!empty($taskClockList)) {
            $taskClockIds = array_column($taskClockList, 'id');
            $taskClock = model(TaskClockModel::class)->where(['id' => ['IN', $taskClockIds]])->delete();
            if (!empty($taskClock)) { //删除关联的闹钟提醒
                model(UncloseTaskClockModel::class)->where(['task_clock_id' => ["IN", $taskClockIds]])->delete();
            }
        }
        return $taskClock;
    }


    /**
     * 获取当前用户的未关闭闹钟
     * @param $filter
     * @param $currentUserId
     * @return array|mixed|string
     */
    public function selectTaskClock($filter, $currentUserId)
    {
        $taskClock = model(TaskClockModel::class)->where(['task_id' => $filter['task_id']])->field('id,task_id,time')->select();

        if (!empty($taskClock)) {
            $uncloseTaskClock = [
                'user_id' => $currentUserId,
                'task_id' => $filter['task_id']
            ];
            $uncloseTaskClock = model(UncloseTaskClockModel::class)->where($uncloseTaskClock)->field('id,task_clock_id')->select();
            $uncloseTaskClockIds = array_column($uncloseTaskClock, 'task_clock_id');
            foreach ($taskClock as &$taskClockItem) {
                if (in_array($taskClockItem['id'], $uncloseTaskClockIds)) {
                    $taskClockItem['is_remind'] = "yes";
                } else {
                    $taskClockItem['is_remind'] = "no";
                }
            }

            return $taskClock;
        } else {
            return [];
        }
    }

    /**
     * 提醒时间列表
     * @param $param
     * @param $currentUser
     * @param $currentTenantId
     * @return array|false|mixed|string|void[]
     * @throws \Exception
     */
    public function selectTaskClockList($param, $currentUser, $currentTenantId)
    {
        $statusList = array_column(model(StatusModel::class)->field('id,code')->select(), 'id', 'code');
//        $stepCategoryId = $param['filter']['step_category_id'];
        $taskWorkOrderService = TaskWorkOrderService::getInstance();
//        $module = $taskWorkOrderService->getModuleByStepCategoryId($stepCategoryId);
        $filter = $taskWorkOrderService->parseMultipleEntityTaskFilter($param['filter']);
        $filter['step_type'] = 'step';
//        $filter['entity.module_id'] = $module['id'];
        $filter['unclose_task_clock.user_id'] = $currentUser;
        $filter['task_clock.time'] = ['LT', time()];
        $filter["JSON_UNQUOTE(JSON_EXTRACT(entity.json, CONCAT('$.', module.code, '_status')))"] = ['NEQ', $statusList['closed']];

        $taskFiled = ["unclose_task_clock.id,task.id as task_id", "task.entity_id", "entity.initial_episode_code",
            "task.executor", "entity.showings_number", "entity.name as entity_name", "task.executor_tenant_id", "task.tenant_id", "task.name as step_name",
            "status.name as status_name,unclose_task_clock.task_clock_id", "entity.entity_id as entity_entity_id", "entity.entity_module_id",
            "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',module.`code`,'_category') )) AS category",
            "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',module.`code`,'_grade') )) AS grade"
        ];


        $uncloseTaskClockQuery = model(UncloseTaskClockModel::class)
            ->join('task_clock on task_clock.id = unclose_task_clock.task_clock_id')
            ->join('task on task.id = unclose_task_clock.task_id')
            ->join('entity on entity.id = task.entity_id')
            ->join('module on module.id = entity.module_id')
            ->join("status on status.id = JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))");

        //如果存在
        if (!empty($filter['task_work_order']['status']) && $filter['task_work_order']['status'] === 0) {
            $uncloseTaskClockQuery->join("task_work_order on task.id = task_work_order and task_work_order.type = 'task_making' ");
        }

        $page = $param['page'] ?? [1, C('default_page_total')];
        //查询出延期任务
        $uncloseTaskClockList = $uncloseTaskClockQuery
            ->where($filter)
            ->field($taskFiled)
            ->page($page[0], $page[1])
            ->select();

        if (!empty($uncloseTaskClockList)) {
            $taskIds = array_column($uncloseTaskClockList, 'task_id', 'task_id');
            $versionMap = [];
            $taskWorkOrderMap = [];
            if (!empty($taskIds)) {
                $maxVersionIds = model(VersionModel::class)->where([
                    'link_id' => ["IN", $taskIds]
                ])->field('max(id) as id')->group('link_id')->select();
                if (!empty($maxVersionIds)) {
                    $maxVersionIds = array_column($maxVersionIds, 'id');
                    $versionIds = model(VersionModel::class)->where([
                        'id' => ["IN", $maxVersionIds]
                    ])->field('id,link_id,number')->select();
                    $versionMap = array_column($versionIds, null, 'link_id');
                }

                //工单状态
                $maxTaskWorkOrderIds = model(TaskWorkOrderModel::class)->where([
                    'task_id' => ["IN", $taskIds],
                    'type' => "task_making"
                ])->field('max(id) as id')->group('task_id')->select();

                if (!empty($maxTaskWorkOrderIds)) {
                    $maxTaskWorkOrderIds = array_column($maxTaskWorkOrderIds, 'id');
                    $taskWorkOrderIds = model(TaskWorkOrderModel::class)->where([
                        'id' => ["IN", $maxTaskWorkOrderIds]
                    ])->field('task_id,status')->select();
                    $taskWorkOrderMap = array_column($taskWorkOrderIds, 'status', 'task_id');
                }
            }

            //执行人获取
            $parentEntityIdList = [];
            $outsideSupplierTenantId = [];
            $executorUserIdList = [];
            foreach ($uncloseTaskClockList as $uncloseTaskClockListItem) {
                if ($uncloseTaskClockListItem['executor_tenant_id'] > 0 && $uncloseTaskClockListItem['executor_tenant_id'] != $currentTenantId) {
                    $outsideSupplierTenantId[$uncloseTaskClockListItem['executor_tenant_id']] = $uncloseTaskClockListItem['executor_tenant_id'];
                } else if ($uncloseTaskClockListItem['executor'] > 0) {
                    $executorUserIdList[$uncloseTaskClockListItem['executor']] = $uncloseTaskClockListItem['executor'];

                }

                if ($uncloseTaskClockListItem['entity_entity_id'] > 0) {
                    $parentEntityIdList[$uncloseTaskClockListItem['entity_entity_id']] = $uncloseTaskClockListItem['entity_entity_id'];
                }
            }


            $taskWorkOrderService = TaskWorkOrderService::getInstance();
            $sequenceList = $taskWorkOrderService->getEntityListMap($parentEntityIdList);

            //执行人查询
            $taskService = TaskService::getInstance();
            $supplierRes = $taskService->queryTaskSupplierInfo($currentTenantId, [], array_values($outsideSupplierTenantId), [], array_values($executorUserIdList));


            $taskClockId = array_column($uncloseTaskClockList, 'task_clock_id');
            $taskClock = [];
            if (!empty($taskClockId)) {
                $taskClock = model(TaskClockModel::class)->where(['id' => ['IN', $taskClockId]])->field('id,time')->select();
                $taskClock = array_column($taskClock, 'time', 'id');
            }

            $dataFormatCallback = function ($item) use ($versionMap, $taskWorkOrderMap, $supplierRes, $taskClock) {
                $item['task_work_order_type'] = 'task_making';
                //版本补充
                $item['version_number'] = null;
                $item['version_id'] = 0;
                if (array_key_exists($item['task_id'], $versionMap)) {
                    $item['version_id'] = $versionMap[$item['task_id']]['id'];
                    $item['version_number'] = $versionMap[$item['task_id']]['number'];
                }

                //工单补充
                $item['task_work_order_status'] = null;
                if (array_key_exists($item['task_id'], $taskWorkOrderMap)) {
                    $item['task_work_order_status'] = $taskWorkOrderMap[$item['task_id']];
                }

                //时间补充
                $item['time'] = $taskClock[$item['task_clock_id']];

                //执行人名字
                $item['executor_name'] = "";
                if ($item['executor_tenant_id'] > 0 && $item['executor_tenant_id'] != $item['tenant_id']) {
                    $item['executor_name'] = $supplierRes['outside'][$item['executor_tenant_id']]['name'] ?? "";
                } elseif ($item['executor'] > 0) {
                    $item['executor_name'] = $supplierRes['executor'][$item['executor']]['name'] ?? "";
                }
                return $item;
            };


            $dataFormatCallbackSub = $dataFormatCallback;
            $dataFormatCallback = function ($item) use (&$dataFormatCallbackSub, &$sequenceList) {
                $item = $dataFormatCallbackSub($item);
                if (isset(Module::$moduleDictData['module_index_by_id'][$item['entity_module_id']]['code'])) {
                    $item[Module::$moduleDictData['module_index_by_id'][$item['entity_module_id']]['code']] = $sequenceList[$item['entity_entity_id']]['name'] ?? "";
                }
                return $item;
            };
            $uncloseTaskClockList = array_map($dataFormatCallback, $uncloseTaskClockList);

        }

        return $uncloseTaskClockList;
    }
}
